import 'dart:async';

import 'package:built_collection/built_collection.dart';
import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:learning_content_admin_pannel.core/core/domain/entities/learning_content/lexical_item/lexical_item.dart';
import 'package:learning_content_admin_pannel.core/core/domain/repositories/learning_content_repository/repository.dart';
import 'package:learning_content_admin_pannel.core/core/domain/repositories/lexical_item_image_api_repository/repository.dart';

part 'failures.dart';

part 'result.dart';

abstract class DeleteWordImage {
  Future<Either<WordImageDeletionFailure, WordImageDeletionResult>> call({
    required String wordId,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
  });
}

class DeleteWordImageImpl implements DeleteWordImage {
  const DeleteWordImageImpl({
    required LexicalItemImageApiRepository lexicalItemImageApiRepository,
    required LearningContentRepository learningContentRepository,
  })  : _lexicalItemImageApiRepository = lexicalItemImageApiRepository,
        _learningContentRepository = learningContentRepository;

  final LexicalItemImageApiRepository _lexicalItemImageApiRepository;
  final LearningContentRepository _learningContentRepository;

  @override
  Future<Either<WordImageDeletionFailure, WordImageDeletionResult>> call({
    required String wordId,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
  }) async {
    final word = lexicalItemMap[wordId] as Word;

    final lexicalItemImageDeletionFailureOrSuccess =
        await _lexicalItemImageApiRepository.deleteLexicalItemImage(
      imageId: word.imageId!,
    );

    if (lexicalItemImageDeletionFailureOrSuccess.isLeft()) {
      const failure = WordImageDeletionFailure();
      return left(failure);
    }

    final updatedWord = word.copyWith(
      imageId: () => null,
    );

    final updatedLexicalItemMap = lexicalItemMap.rebuild((lexicalItemMap) {
      lexicalItemMap[updatedWord.id] = updatedWord;
    });

    unawaited(_learningContentRepository.saveLexicalItems(
      lexicalItems: updatedLexicalItemMap.values.toBuiltList(),
    ));

    final result = WordImageDeletionResult(
      cachedWordImagePath: null,
      lexicalItemMap: updatedLexicalItemMap,
    );

    return right(result);
  }
}
